
package br.ufu.lsi.database.collector.old;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import twitter4j.Paging;
import twitter4j.RateLimitStatus;
import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import br.ufu.lsi.util.FileUtil;
import br.ufu.lsi.util.PropertiesUtil;

import com.google.gson.Gson;

public class TimelineThread implements Runnable {

    private static final String FOLLOWERS_DIR = PropertiesUtil.getProperty( "FOLLOWERS_DIR" );

    private static final String TIMELINES_DIR = PropertiesUtil.getProperty( "TIMELINES_DIR" );

    private static final Integer BUFFER_SIZE = PropertiesUtil.getIntProperty( "BUFFER_SIZE" );

    private long userId;

    private Twitter twitter;

    private String extension;

    private List< Long > followers = new ArrayList< Long >();
    
    private int requestsCounter = 0;
    
    private String token;
    
    
    private long counter = 0;

    public TimelineThread( Twitter twitter, long userId, String extension ) throws Exception {
        this.userId = userId;
        this.twitter = twitter;
        this.extension = extension;
        this.token = twitter.getOAuthAccessToken().getToken();
    }

    public void run() {

        try {

            readFollowers();

        } catch ( Exception e ) {

            e.printStackTrace();
        }
    }

    public void readFollowers() throws Exception {

        BufferedReader br = FileUtil.openInputFile( FOLLOWERS_DIR + userId + extension );
        String line;
        while ( ( line = br.readLine() ) != null ) {

            followers.add( Long.parseLong( line ) );
            if ( followers.size() > BUFFER_SIZE ) {
                readTimelines();
                followers.clear();
            }
        }
        readTimelines();
        br.close();
    }

    public void readTimelines() throws Exception {

        for ( Long followerId : followers ) {

            BufferedWriter bw = FileUtil.openOutputFile( TIMELINES_DIR + userId + "/" + followerId );

            System.out.print( "(" + token + ") Timeline from "
                    + followerId + "..." );

            /*Paging paging = new Paging( 1, 5000 );
            int i = 0;
            for ( int page = 1;; page++ ) {
                paging.setPage( page );
                ResponseList< Status > results = timeline( twitter, followerId, paging );

                if ( results == null || results.isEmpty() )
                    break;
                for ( Status tweet : results ) {
                    String json = TwitterObjectFactory.getRawJSON( tweet );
                    bw.write( json + "\n" );
                    ++ i;
                }
            }
            System.out.println( "OK " + i );
             bw.close();
            */
            
            
            List<Status> statuses = new ArrayList<Status>();
            int pageno = 1;
            while (true) {

                try {

                  int size = statuses.size(); 
                  Paging page = new Paging(pageno++, 200);
                  //statuses.addAll(twitter.getUserTimeline(followerId, page));
                  counter++;
                  statuses.addAll( timeline( twitter, followerId, page) );
                  if (statuses.size() == size)
                    break;
                }
                catch( Exception e) {
 
                  e.printStackTrace();
                }
            }
            for ( Status tweet : statuses ) {
                
                Gson gson = new Gson();
                String json = gson.toJson( tweet );
                
                /*String json = TwitterObjectFactory.getRawJSON( tweet );
                System.out.println( json );*/
                bw.write( json + "\n" );
            }
              
            System.out.println("(" + token + ") OK " + statuses.size());
            bw.close();            
            
        }
    }

    public List< Status > timeline( Twitter twitter, long followerId, Paging paging ) throws Exception {

        try {
            
            
            requestsCounter++;
            System.out.println( "\n(" + token + ") calling timeline for page " + paging.getPage() + "... ");
            List<Status> statuses = twitter.getUserTimeline( followerId, paging );
            System.out.println( statuses.size() );
            counter--;
            return statuses;

        } catch ( TwitterException e ) {

            System.out.println("\n-------------------------------> " + e.getErrorMessage() + " (" + e.getStatusCode() + ") " );
            
            
            if ( e.getStatusCode() == 429 ) {
                
                System.out.println( "Counter: " + counter );
                
                RateLimitStatus status = e.getRateLimitStatus();
                System.out.println( "\n" + new Date( System.currentTimeMillis() )
                        + " Sleeping thread " + Thread.currentThread().getName() + " during "
                        + status.getSecondsUntilReset() + "sec ( "
                        + token + " errCode=" + e.getStatusCode() + " requestCounter=" + requestsCounter + " ) ..." );

                requestsCounter = 0;
                /*if ( status.getSecondsUntilReset() > 0 )
                    Thread.sleep( status.getSecondsUntilReset() * 1000 );
                */
                // sleep 17 min
                Thread.sleep( 1020000L );
                
                counter++;
                return timeline( twitter, followerId, paging );
            }
            
            counter--;
        } catch( Exception e ) {
            e.printStackTrace();
        }
        return new ArrayList<Status>();
    }

}
